package com.bc004346.travelus;

import android.app.Activity;
import android.app.Fragment;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.bc004346.travelus.adapter.FlightAdapterWithAvailability;
import com.bc004346.travelus.dataAccess.TravelUsScreenScraper;
import com.bc004346.travelus.dataAccess.asyncTasks.GetAvailablePassengersTaskFragment;
import com.bc004346.travelus.dataAccess.asyncTasks.SearchFlightsTaskFragment;
import com.bc004346.travelus.dataAccess.asyncTasks.SelectFlightTaskFragment;
import com.bc004346.travelus.model.TravelUsUnavailableException;
import com.bc004346.travelus.model.domain.Flight;
import com.bc004346.travelus.model.domain.FlightSearchParams;
import com.bc004346.travelus.model.domain.Passenger;
import com.bc004346.travelus.model.interfaces.IFlightAvailabilityRequestListener;
import com.bc004346.travelus.model.interfaces.IPBTTrackerListener;
import com.bc004346.travelus.model.interfaces.ISearchFlightsCallback;
import com.bc004346.travelus.model.interfaces.ISelectFlightCallback;
import com.bc004346.travelus.model.interfaces.ISelectFlightListener;
import com.bc004346.travelus.model.interfaces.ISelectPassengersCallback;
import com.bc004346.travelus.utility.Utility;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

import static com.bc004346.travelus.utility.Utility.DATE;
import static com.bc004346.travelus.utility.Utility.DEPARTURE;
import static com.bc004346.travelus.utility.Utility.DESTINATION;
import static com.bc004346.travelus.utility.Utility.IS_ONE_WAY;
import static com.bc004346.travelus.utility.Utility.ORIGIN;
import static com.bc004346.travelus.utility.Utility.RETURN;
import static com.bc004346.travelus.utility.Utility.SEARCH_TASK_TAG;
import static com.bc004346.travelus.utility.Utility.SELECT_FLIGHT_TAG;
import static com.bc004346.travelus.utility.Utility.SELECT_PASSENGERS_TAG;
import static com.bc004346.travelus.utility.Utility.UPDATE_FLIGHT_AVAILABILITY_TAG;
import static com.bc004346.travelus.utility.Utility.log;
import static com.bc004346.travelus.utility.Utility.onActivityStart;
import static com.bc004346.travelus.utility.Utility.onActivityStop;

/**
 * Created by Renats on 3/23/14.
 * flight selection activity
 */
public class FlightSelectionActivity
        extends Activity
        implements ISearchFlightsCallback,
        ISelectFlightListener,
        IFlightAvailabilityRequestListener,
        ISelectFlightCallback,
        ISelectPassengersCallback,
        IPBTTrackerListener {

    //<editor-fold desc="Members">

    private FlightAdapterWithAvailability mFlightAdapter;
    private TextView mTextViewMessage;
    private ProgressBar mProgressBar;
    private Button mButton;
    private String mOrigin;
    private String mDestination;
    private String mDeparture;
    private String mReturn;

    //</editor-fold>
    //<editor-fold desc="Overrides">

    @Override
    protected void onStart() {
        super.onStart();
        onActivityStart(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        onActivityStop(this);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        try {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_flight_selection);
            ListView listView = (ListView) findViewById(R.id.flightList);
            mTextViewMessage = (TextView) findViewById(R.id.flightSelectionTextViewMessage);
            mButton = (Button) findViewById(R.id.flightSelectionButtonContinue);
            mProgressBar = (ProgressBar) findViewById(R.id.activity_flight_selection_progressBar);

            Intent intent = getIntent();
            mOrigin = intent.getStringExtra(ORIGIN);
            mDestination = intent.getStringExtra(DESTINATION);
            mDeparture = intent.getStringExtra(DEPARTURE);
            mReturn = intent.getStringExtra(RETURN);
            final Boolean isOneWay = intent.getBooleanExtra(IS_ONE_WAY, true);

            mButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    handleButtonClick(isOneWay, mOrigin, mDestination, mDeparture, mReturn);
                }
            });

            ArrayList<Flight> flights = Utility.flightsSelection;
            mFlightAdapter = new FlightAdapterWithAvailability(this, flights);
            listView.setAdapter(mFlightAdapter);
        } catch (Exception e) {
            mTextViewMessage.setText(e.getMessage());
            log(e, this);
        }
    }

    void handleButtonClick(Boolean isOneWay, String origin, String destination, String departure, String returnDate) {

        try {
            if (isOneWay) {
                mButton.setText(getString(R.string.common_working));
                if (noOtherWorkInProgress()) {
                    mProgressBar.setVisibility(View.VISIBLE);
                    GetAvailablePassengersTaskFragment selectPassengerFragment =
                            GetAvailablePassengersTaskFragment.newInstance(origin, destination, departure);
                    getFragmentManager().beginTransaction()
                            .add(selectPassengerFragment, SELECT_PASSENGERS_TAG)
                            .commitAllowingStateLoss();
                } else mTextViewMessage.setText(getString(R.string.common_please_wait));
            } else {
                mButton.setText(getString(R.string.bookTravel_ButtonSearchTextAlt));
                mButton.setEnabled(false);
                if (noOtherWorkInProgress()) {
                    mProgressBar.setVisibility(View.VISIBLE);
                    FlightSearchParams params = new FlightSearchParams();
                    params.setOrigin(origin);
                    params.setDestination(destination);
                    params.setDeparture(DATE.parse(departure));
                    params.setReturn(DATE.parse(returnDate));
                    params.setIsOneWay(isOneWay);
                    SearchFlightsTaskFragment searchFlightFragment = SearchFlightsTaskFragment.newInstance(
                            params,
                            true);
                    getFragmentManager().beginTransaction().add(searchFlightFragment, SEARCH_TASK_TAG).commitAllowingStateLoss();
                } else mTextViewMessage.setText(getString(R.string.common_please_wait));
            }
        } catch (ParseException e) {
            mTextViewMessage.setText(e.getMessage());
            mProgressBar.setVisibility(View.INVISIBLE);
            log(e, this);
        }
    }

    @Override
    public void selectFlight(Flight flight) {
        try {
            if (noOtherWorkInProgress()) {
                mProgressBar.setVisibility(View.VISIBLE);
                mButton.setText(R.string.common_working);
                SelectFlightTaskFragment fragment = SelectFlightTaskFragment.newInstance(flight);
                getFragmentManager().beginTransaction().add(fragment, SELECT_FLIGHT_TAG).commitAllowingStateLoss();
            } else
                mTextViewMessage.setText(getString(R.string.common_please_wait));
        } catch (Exception e) {
            mProgressBar.setVisibility(View.INVISIBLE);
            mTextViewMessage.setText(e.getMessage());
            log(e, this);
        }
    }

    @Override
    public void onSelectFlightPostExecute(Flight flight, Exception e) {
        try {
            mProgressBar.setVisibility(View.INVISIBLE);
            mTextViewMessage.setText("");
            removeFragment(SELECT_FLIGHT_TAG);
            mButton.setText(R.string.common_continue);

            if (e != null) {
                if (e.getClass() == TravelUsUnavailableException.class) {
                    log(e);
                    mTextViewMessage.setText("Travel US is having problems processing your request. It may be down right now");
                } else {
                    mTextViewMessage.setText(e.getMessage());
                    mFlightAdapter.deselectFlight(flight);
                    log(e, this);
                }
            }
        } catch (Exception e1) {
            mTextViewMessage.setText(e.getMessage());
            log(e1, this);
        }
    }

    @Override
    public void onSelectPassengersPostExecute(List<Passenger> passengers, Exception e) {
        try {
            mProgressBar.setVisibility(View.INVISIBLE);
            mTextViewMessage.setText("");
            removeFragment(SELECT_PASSENGERS_TAG);

            if (e != null) {
                if (e.getClass() == TravelUsUnavailableException.class) {
                    log(e);
                    mTextViewMessage.setText("Travel US is having problems processing your request. It may be down right now");
                } else {
                    mButton.setText(getString(R.string.common_continue));
                    mTextViewMessage.setText(e.getMessage());
                    log(e, this);
                }
                return;
            }
            Utility.paxSelection = passengers;

            Intent intent = new Intent(this, ContactDetailsActivity.class);
            startActivity(intent);
            finish();
        } catch (Exception e1) {
            mTextViewMessage.setText(e1.getMessage());
            log(e1, this);
        }
    }

    @Override
    public void onSearchPostExecute(ArrayList<Flight> flights, Exception e) {
        try {
            mProgressBar.setVisibility(View.INVISIBLE);
            mButton.setText(getString(R.string.bookTravel_ButtonSearchText));
            mButton.setEnabled(true);
            removeFragment(SEARCH_TASK_TAG);

            if (e != null) {
                if (e.getClass() == TravelUsUnavailableException.class) {
                    log(e);
                    mTextViewMessage.setText("Travel US is having problems processing your request. It may be down right now");
                } else {
                    mTextViewMessage.setText(e.getMessage());
                    log(e, this);
                }
                return;
            }

            if (flights == null || flights.size() == 0) {
                mTextViewMessage.setText(getString(R.string.common_no_flights_found));
                return;
            }

            Utility.flightsSelection = flights;

            Intent intent = new Intent(this, FlightSelectionActivity.class);
            intent.putExtra(ORIGIN, mOrigin);
            intent.putExtra(DESTINATION, mDestination);
            intent.putExtra(DEPARTURE, mDeparture);
            intent.putExtra(RETURN, mReturn);
            intent.putExtra(IS_ONE_WAY, true);
            startActivity(intent);

            finish();

        } catch (Exception ex) {
            mTextViewMessage.setText(ex.getMessage());
            log(ex, this);
        }
    }

    @Override
    public void updateFlightAvailability(Flight flight) {
        try {
            if (noOtherWorkInProgress()) {
                mButton.setText(R.string.common_working);
                mProgressBar.setVisibility(View.VISIBLE);


                new AsyncTask<Flight, Void, Flight>() {

                    private Exception exception;

                    @Override
                    protected Flight doInBackground(Flight... params) {
                        Flight flight = params[0];
                        try {
                            TravelUsScreenScraper travelUsScreenScraper =
                                    Utility.getInstance().getBackgroundTravelUS();
                            flight = travelUsScreenScraper.checkAvailability(flight);
                        } catch (Exception e) {
                            exception = e;
                        }
                        return flight;
                    }

                    @Override
                    protected void onPostExecute(Flight flight) {
                        if (exception == null) {
                            mProgressBar.setVisibility(View.INVISIBLE);
                            mButton.setText(R.string.common_continue);
                            mTextViewMessage.setText("");
                            mFlightAdapter.updateFlight(flight);
                        } else {
                            if (exception.getClass() == TravelUsUnavailableException.class) {
                                log(exception);
                                mTextViewMessage.setText("Travel US is having problems processing your request. It may be down right now");
                            } else {
                                mButton.setText(getString(R.string.common_continue));
                                mTextViewMessage.setText(exception.getMessage());
                                log(exception, FlightSelectionActivity.this);
                            }
                        }
                    }
                }.execute(flight);

            } else
                mTextViewMessage.setText(getString(R.string.common_please_wait));
        } catch (Exception e) {
            mProgressBar.setVisibility(View.INVISIBLE);
            mTextViewMessage.setText(e.getMessage());
            log(e, this);
        }
    }

    @Override
    public boolean togglePBT(final Flight flight) {
        try {
            if (noOtherWorkInProgress()) {
                mProgressBar.setVisibility(View.VISIBLE);
                mButton.setText(R.string.common_working);

                new AsyncTask<Flight, Void, Void>() {

                    private Exception exception;

                    @Override
                    protected Void doInBackground(Flight... params) {
                        Flight flight = params[0];
                        try {
                            TravelUsScreenScraper travelUsScreenScraper =
                                    Utility.getInstance().getTravelUS();
                            travelUsScreenScraper.togglePBT(flight);
                        } catch (Exception e) {
                            exception = e;
                        }
                        return null;
                    }

                    @Override
                    protected void onPostExecute(Void none) {
                        if (exception == null) {
                            mTextViewMessage.setText("");
                        } else {
                            flight.setTracked(!flight.isTracked());
                            mTextViewMessage.setText(exception.getMessage());
                        }
                    }
                }.execute(flight);

            } else
                mTextViewMessage.setText(getString(R.string.common_please_wait));

        } catch (Exception e) {
            mTextViewMessage.setText(e.getMessage());
            log(e, this);
        } finally {
            mProgressBar.setVisibility(View.INVISIBLE);
            mButton.setText(R.string.common_continue);
        }
        return flight.isTracked();
    }

    //</editor-fold>
    //<editor-fold desc="Private Methods">

    private void removeFragment(String tag) {

        Fragment fragment =
                getFragmentManager().findFragmentByTag(tag);
        if (fragment != null)
            getFragmentManager().beginTransaction().remove(fragment).commitAllowingStateLoss();

    }

    private boolean noOtherWorkInProgress() {
        Fragment f1 = getFragmentManager().findFragmentByTag(SELECT_FLIGHT_TAG);
        Fragment f2 = getFragmentManager().findFragmentByTag(SELECT_PASSENGERS_TAG);
        Fragment f3 = getFragmentManager().findFragmentByTag(SEARCH_TASK_TAG);
        Fragment f4 = getFragmentManager().findFragmentByTag(UPDATE_FLIGHT_AVAILABILITY_TAG);

        return (f1 == null && f2 == null && f3 == null && f4 == null);
    }


    //</editor-fold>
}
